package my.shadowsocks.server;

import io.netty.buffer.ByteBuf;
import my.shadowsocks.common.encryption.Crypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @author fengbo
 * @date 2018/10/5
 */
class CryptUtils {

    private static final Logger log = LoggerFactory.getLogger(CryptUtils.class);

    static byte[] encrypt(Crypt crypt, Object msg) {
        byte[] data = null;
        ByteArrayOutputStream remoteOutStream = null;
        try {
            remoteOutStream = new ByteArrayOutputStream();
            ByteBuf byteBuff = (ByteBuf) msg;
            if (!byteBuff.hasArray()) {
                int len = byteBuff.readableBytes();
                byte[] arr = new byte[len];
                byteBuff.getBytes(0, arr);
                crypt.encrypt(arr, arr.length, remoteOutStream);
                data = remoteOutStream.toByteArray();
            }
        } finally {
            if (remoteOutStream != null) {
                try {
                    remoteOutStream.close();
                } catch (IOException e) {
                    log.error("encrypt error", e);
                }
            }
        }
        return data;
    }

    static byte[] decrypt(Crypt crypt, Object msg) {
        byte[] data = null;
        ByteArrayOutputStream localOutStream = null;
        try {
            localOutStream = new ByteArrayOutputStream();
            ByteBuf byteBuff = (ByteBuf) msg;
            if (!byteBuff.hasArray()) {
                int len = byteBuff.readableBytes();
                byte[] arr = new byte[len];
                byteBuff.getBytes(0, arr);
                crypt.decrypt(arr, arr.length, localOutStream);
                data = localOutStream.toByteArray();
            }
        } finally {
            if (localOutStream != null) {
                try {
                    localOutStream.close();
                } catch (IOException e) {
                    log.error("encrypt error", e);
                }
            }
        }
        return data;
    }

}
